package com.crawl.view;

import com.crawl.zhihu.dao.ZhiHuDao;
import com.crawl.zhihu.dao.ZhiHuDaoImp;
import com.crawl.zhihu.entity.User;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;


import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * http请求处理器
 */
public class HttpRequestHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        String requestMethod = httpExchange.getRequestMethod();
        if (requestMethod.equalsIgnoreCase("GET")) {
            process(httpExchange);
        }
    }

    /**
     * 具体请求处理方法
     * @param httpExchange
     * @throws IOException
     */
    private void process(HttpExchange httpExchange) throws IOException {httpExchange.sendResponseHeaders(200, 0);
        //获取response流
        OutputStream responseBody = httpExchange.getResponseBody();
        List<ChartVO> chartVOList = new ArrayList<>();
        //创建可视化vo对象
        chartVOList.add(new ChartVO("followers", "粉丝数", "知乎粉丝数TOP10"));
        chartVOList.add(new ChartVO("agrees", "赞同数", "知乎赞同数TOP10"));
        chartVOList.add(new ChartVO("thanks", "感谢数", "知乎感谢数TOP10"));
        chartVOList.add(new ChartVO("asks", "提问数", "知乎提问数TOP10"));
        chartVOList.add(new ChartVO("answers", "回答数", "知乎回答数TOP10"));
        chartVOList.add(new ChartVO("posts", "文章数", "知乎文章数TOP10"));
        chartVOList.add(new ChartVO("followees", "关注数", "知乎关注数TOP10"));
        for(ChartVO vo : chartVOList){
            //调用本类中方法
            getTop10(vo);
        }
        ZhiHuDao zhiHuDao = new ZhiHuDaoImp();
        String educationSQL = "select education as name, count(*) as count from user where education is not null group by education order by count(*) desc limit 0, 10";
        List<TopVO> topVOList = zhiHuDao.queryTopList(educationSQL);

        //调用本类中方法，渲染数据
        String response = render(chartVOList, getTopVO(topVOList, "top10学校用户数"));
        //write数据至response流中
        responseBody.write(response.getBytes());
        responseBody.close();
    }

    /**
     * 根据vo对象，从数据库中查询对应数据top10 user
     * 并通过反射，获取对应字段的值，然后构造前端所需要数据格式数据
     * @param vo
     * @return
     */
    private ChartVO getTop10(ChartVO vo){
        //创建数据库操作对象
        ZhiHuDao zhiHuDao = new ZhiHuDaoImp();
        //创建sql查询语句
        String followersTop10Sql = "select * from user order by " + vo.getColumnName() + " desc limit 0, 10";
        //根据sql查询数据
        List<User> userList = zhiHuDao.queryUserList(followersTop10Sql);

        //创建前端页面echarts横坐标数组字符串对象
        StringBuilder xAxis = new StringBuilder();
        //创建前端页面echarts纵坐标数据数组字符串对象
        StringBuilder series = new StringBuilder();
        xAxis.append("[");
        series.append("[");

        //根据字段名，构造对应字段get方法名，eg:字段名为followers,则对应get方法名为getFollowers
        StringBuilder methodName = new StringBuilder(vo.getColumnName());
        int c = methodName.charAt(0);
        c =  c - 32;
        methodName.deleteCharAt(0);
        methodName.insert(0, (char) c);
        Method method = null;
        try {
            //获取字段对应method对象
            method = User.class.getMethod("get" + methodName);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        //设置数据
        for (User user : userList){
            xAxis.append("'" + user.getUsername() + "',");
            try {

                int value = (int) method.invoke(user);
                series.append("'" + value + "',");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        xAxis.deleteCharAt(xAxis.length() - 1);
        series.deleteCharAt(series.length() - 1);
        xAxis.append("]");
        series.append("]");
        vo.setxAxis(xAxis.toString());
        vo.setSeries(series.toString());
        return vo;
    }

    private TopChartVO getTopVO(List<TopVO> voList, String titleText){
        TopChartVO topChartVO = new TopChartVO();
        topChartVO.setTitleText(titleText);
        topChartVO.setColumnName("edcuation");
        topChartVO.setColumnDesc("学校用户数");
        //创建前端页面echarts横坐标数组字符串对象
        StringBuilder xAxis = new StringBuilder();
        //创建前端页面echarts纵坐标数据数组字符串对象
        StringBuilder series = new StringBuilder();
        xAxis.append("[");
        series.append("[");


        //设置数据
        for (TopVO topVO : voList){
            xAxis.append("'" + topVO.getName() + "',");
            series.append("'" + topVO.getCount() + "',");
        }
        xAxis.deleteCharAt(xAxis.length() - 1);
        series.deleteCharAt(series.length() - 1);
        xAxis.append("]");
        series.append("]");
        topChartVO.setxAxis(xAxis.toString());
        topChartVO.setSeries(series.toString());
        return topChartVO;
    }

    /**
     * 通过velocity模板引擎渲染前端页面
     * @param chartVOList 数据源
     * @return
     */
    private String render(List<ChartVO> chartVOList, TopChartVO topChartVO){
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        prop.setProperty(Velocity.ENCODING_DEFAULT, "utf-8");
        prop.setProperty(Velocity.INPUT_ENCODING, "utf-8");
        prop.setProperty(Velocity.OUTPUT_ENCODING, "utf-8");
        prop.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogChute"); // disable velocity.log
        Velocity.init(prop);

        Template t = Velocity.getTemplate("/charts-template.vm");
        VelocityContext ctx = new VelocityContext();
        ctx.put("chartVOList", chartVOList);
        ctx.put("topChartVO", topChartVO);
        StringWriter sw = new StringWriter();
        t.merge(ctx, sw);
        return sw.toString();
    }
}
